package com.xp.tinyurl.service;

import com.xp.tinyurl.common.cache.MaxUuidCache;
import com.xp.tinyurl.common.utils.FeistelCipher;
import com.xp.tinyurl.common.utils.SnowflakeIdWorker;
import com.xp.tinyurl.model.ShortUrlMap;
import com.xp.tinyurl.service.thirdprovider.vo.UpushShorterUrlResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 短链生成器
 *
 * @author  (xp)
 **/
@Service
public class ShortUrlGenerator {
    private static final Logger LOGGER = LoggerFactory.getLogger(ShortUrlGenerator.class);
    /**
     * 尝试生成permutedId的次数
     */
    private static final int TRY_FEISTEL_CIPHER_TIMES = 4;
    /**
     * 尝试生成shortUrl的次数
     */
    private static final int TRY_GENERATE_SHORT_URL_TIMES = 4;

    @Autowired
    private ShortUrlMapSddlService shortUrlMapSddlService;

    @Autowired
    private MaxUuidService maxUuidService;

    public UpushShorterUrlResult generate(String mainDomainName) {
        for (int i = 0; i < TRY_GENERATE_SHORT_URL_TIMES; i++) {
            UpushShorterUrlResult shorterUrlResult = doGenerate();
            if (shorterUrlResult.isSuccess()) {
                ShortUrlMap history = shortUrlMapSddlService.getActiveByShortUrl(shorterUrlResult.getUuid());
                if (history == null) {
                    return shorterUrlResult;
                }
                LOGGER.warn("[{}] currentUUid: {}, already exists the same shortUrl: {} [uuid: {}, id: {}, createTime: {}]", i, shorterUrlResult.getUuid(),
                        history.getShortUrl(), history.getUuid(), history.getId(), history.getCreateTime());
            } else {
                LOGGER.error("fail to doGenerate shortUrl, just skip");
                break;
            }
        }

        return UpushShorterUrlResult.fail();
    }

    /**
     * get最大uuid
     */
    public UpushShorterUrlResult doGenerate() {
        long uuid = UpushShorterUrlResult.NOT_VALID;
        long permutedId = UpushShorterUrlResult.NOT_VALID;

        for (int i = 0; i < TRY_FEISTEL_CIPHER_TIMES; i++) {
            uuid = maxUuidService.getMaxUuid();
            permutedId = FeistelCipher.permutedId(uuid);
            if (permutedId >= 0) {
                break;
            }
        }

        if (permutedId < 0) {
            LOGGER.error("feistel排列得到负值，尝试{}次后失败, 当前uuid: {}, permutedId: {}", TRY_FEISTEL_CIPHER_TIMES, uuid, permutedId);
            return UpushShorterUrlResult.fail(permutedId, permutedId);
        }
        return UpushShorterUrlResult.success(permutedId, permutedId);
    }
}
